package com.szakul.pdf;

import java.io.InputStream;
import java.util.List;

import com.szakul.pdf.gui.InfoLayout;
import com.szakul.pdf.layout.ViolationsForm;

import com.szakul.pdf.model.Page;
import com.szakul.pdf.model.TreePageModel;
import com.szakul.pdf.model.ViewModel;
import com.szakul.pdf.model.Zoom;

import com.vaadin.data.Property.ValueChangeListener;
import com.vaadin.data.util.HierarchicalContainer;

import com.vaadin.event.Action;
import com.vaadin.event.ItemClickEvent;

import com.vaadin.event.ItemClickEvent.ItemClickListener;

import com.vaadin.terminal.Sizeable;

import com.vaadin.terminal.ThemeResource;

import com.vaadin.ui.Button;
import com.vaadin.ui.CustomLayout;

import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.HorizontalSplitPanel;

import com.vaadin.ui.Alignment;
import com.vaadin.ui.GridLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.Panel;

import com.vaadin.ui.RichTextArea;
import com.vaadin.ui.TabSheet;
import com.vaadin.ui.Table;
import com.vaadin.ui.TextField;
import com.vaadin.ui.Tree;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.VerticalSplitPanel;
import com.vaadin.ui.Window;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;

import com.vaadin.ui.Table.TableDragMode;

import com.vaadin.ui.themes.BaseTheme;
import com.vaadin.ui.themes.Reindeer;
import com.vaadin.ui.themes.Runo;

public class Viewer extends Window {

	private static final ThemeResource DOCUMENT_PDF = new ThemeResource(
    "icons/16/document-pdf.png");

	
	private ViewModel dataModel;

	private CustomLayout cssLayout;

	private HorizontalSplitPanel horizontalSplitPanel;

	private VerticalSplitPanel verticalSplitPanel;

	private Panel mainPanel = new Panel();
	private Panel topPanel = new Panel();
	private Panel leftPanel = new Panel();
	private Panel rightPanel = new Panel();

	private HorizontalLayout menuLayout;
	private Table pdfTable;
	private Tree tree;

	private Button upButton;
	private Button downButton;
	private Button zoomOut;
	private Button zoomIn;
	private Button searchButton;

	private Button searchNext;
	private Button searchPrev;

	private TextField pages;
	private TextField searchText;

	private Label allPages;
	private Label zoomLabel;
	private Label searchLabel;

	private Window subwindow;
	private HorizontalSplitPanel pdfWindow;

	private VerticalLayout searchContent = new VerticalLayout();
	
	private InfoLayout infoPanel;

	private TabSheet tabsheet = new TabSheet();
	
	/**
	 * @return the editor
	 */
	public RichTextArea getEditor() {
		return editor;
	}

	private final RichTextArea editor = new RichTextArea();
	
	public Viewer(ViewModel dataModel) {
		super();
		this.dataModel = dataModel;
	}

	private void initLayout() {
		createZoomlabel();

		createZoomInButton();
		createZoomOutButton();
		createAllPagesLabel();
		createTextFieldPages();
		createUpButton();
		createDownButton();
		createTree();
		createTable();
		createMenuLayout();
		creatCustomLayout();

		mainPanel.setSizeFull();

		addComponent(cssLayout);

		cssLayout.setSizeFull();
		cssLayout.addComponent(mainPanel, "pdfForm");
		cssLayout.setImmediate(true);

		verticalSplitPanel = new VerticalSplitPanel();
		verticalSplitPanel.setSplitPosition(100, Sizeable.UNITS_PIXELS);
		verticalSplitPanel.setLocked(true);
		verticalSplitPanel.setHeight("800px");
		verticalSplitPanel.setWidth("100%");
		verticalSplitPanel.setMargin(false);
		verticalSplitPanel.setStyleName(Runo.PANEL_LIGHT);

		mainPanel.addComponent(verticalSplitPanel);
		mainPanel.setImmediate(true);

		// Add some content to the top
		topPanel.setSizeFull();
		verticalSplitPanel.addComponent(topPanel);

		// Add a horizontal split panel in the bottom area
		horizontalSplitPanel = new HorizontalSplitPanel();
		horizontalSplitPanel.setSplitPosition(25, Sizeable.UNITS_PERCENTAGE);
		horizontalSplitPanel.setSizeFull();
		horizontalSplitPanel.setLocked(true);
		horizontalSplitPanel.setStyleName(Runo.PANEL_LIGHT);
		verticalSplitPanel.addComponent(horizontalSplitPanel);

		// Add some content to the left and right sides of the vertical layout
		leftPanel.setSizeFull();
		horizontalSplitPanel.addComponent(leftPanel);
		tabsheet.setSizeFull();
		tabsheet.setImmediate(true);
		horizontalSplitPanel.addComponent(tabsheet);
		rightPanel.setWidth("100%");
		rightPanel.setImmediate(true);
		rightPanel.setStyleName(Runo.PANEL_LIGHT);

		pdfWindow = new HorizontalSplitPanel();
		pdfWindow.setSizeFull();
		pdfWindow.setSplitPosition(80, Sizeable.UNITS_PERCENTAGE);
		pdfWindow.setSizeFull();
		pdfWindow.setLocked(true);
		pdfWindow.setStyleName(Reindeer.PANEL_LIGHT);

		GridLayout panelActions = new GridLayout(2, 1);
		panelActions.setSizeFull();

		HorizontalLayout panelPages = new HorizontalLayout();
		HorizontalLayout panelZoom = new HorizontalLayout();

		panelActions.addComponent(panelPages, 0, 0);
		panelActions.addComponent(panelZoom, 1, 0);

		panelPages.addComponent(upButton);
		panelPages.addComponent(downButton);
		panelPages.addComponent(pages);
		panelPages.addComponent(allPages);

		panelZoom.addComponent(zoomIn);
		panelZoom.addComponent(zoomOut);
		panelZoom.addComponent(zoomLabel);

		HorizontalLayout horizontalPanelSearch = new HorizontalLayout();

		horizontalPanelSearch.addComponent(createSearchText());
		horizontalPanelSearch.addComponent(createSearchButton());
		horizontalPanelSearch.addComponent(createSearchNext());
		horizontalPanelSearch.addComponent(createSearchPrev());
		Panel panelSearch = new Panel("Wyszukaj");
		panelSearch.setWidth("100%");
		panelSearch.setHeight("100%");
		panelSearch.addComponent(horizontalPanelSearch);
		panelSearch.addComponent(searchContent);

		rightPanel.addComponent(panelActions);
		rightPanel.addComponent(pdfTable);

		pdfWindow.addComponent(rightPanel);
		pdfWindow.addComponent(panelSearch);

		// left panel
		leftPanel.addComponent(tree);
		
		//right panel
		infoPanel = new InfoLayout();
		infoPanel.setImmediate(true);
		tabsheet.addTab(infoPanel, "Info", DOCUMENT_PDF);
	}

	public void initWindow() {
		initLayout();
	}

	private Button createSearchNext() {

		if (searchNext == null) {
			searchNext = new Button();
		}

		searchNext.setIcon(new ThemeResource("page-next.png"));
		searchNext.setStyleName(BaseTheme.BUTTON_LINK);

		return searchNext;

	}

	private Button createSearchPrev() {

		if (searchPrev == null) {
			searchPrev = new Button();
		}

		searchPrev.setIcon(new ThemeResource("page-previous.png"));
		searchPrev.setStyleName(BaseTheme.BUTTON_LINK);

		return searchPrev;

	}

	private Button createSearchButton() {

		if (searchButton == null) {
			searchButton = new Button();
		}

		searchButton.setIcon(new ThemeResource("find-icon.png"));
		searchButton.setStyleName(BaseTheme.BUTTON_LINK);

		return searchButton;

	}

	private TextField createSearchText() {
		if (searchText == null) {
			searchText = new TextField();
		}

		return searchText;
	}

	private Label createSearchLabel() {
		if (searchLabel == null) {
			searchLabel = new Label();
		}
		searchLabel.setStyleName("h2");
		searchLabel.setCaption("Szukaj");
		return searchLabel;
	}

	private void createAllPagesLabel() {
		if (allPages == null) {
			allPages = new Label();
		}
		allPages.setStyleName("h2");

	}

	private void createZoomlabel() {
		if (zoomLabel == null) {
			zoomLabel = new Label();
		}
		zoomLabel.setStyleName("h2");
	}

	private void createTextFieldPages() {
		if (pages == null) {
			pages = new TextField();

		}
		pages.setMaxLength(3);
		pages.setColumns(4);
		pages.setImmediate(true);
	}

	private void createUpButton() {
		if (upButton == null) {
			upButton = new Button();
		}

		upButton.setIcon(new ThemeResource("up-icon.png"));
		upButton.setStyleName(BaseTheme.BUTTON_LINK);
	}

	private void createDownButton() {
		if (downButton == null) {
			downButton = new Button();
		}

		downButton.setIcon(new ThemeResource("down-icon.png"));
		downButton.setStyleName(BaseTheme.BUTTON_LINK);
	}

	private void createZoomInButton() {
		if (zoomIn == null) {
			zoomIn = new Button();
		}

		zoomIn.setIcon(new ThemeResource("zoomIn.png"));
		zoomIn.setStyleName(BaseTheme.BUTTON_LINK);
		zoomIn.setImmediate(true);
	}

	private void createZoomOutButton() {
		if (zoomOut == null) {
			zoomOut = new Button();
		}

		zoomOut.setIcon(new ThemeResource("zoomOut.png"));
		zoomOut.setStyleName(BaseTheme.BUTTON_LINK);
		zoomOut.setImmediate(true);
	}

	private void createTable() {

		if (pdfTable == null) {

			pdfTable = new Table();
		}

		pdfTable.setHeight("600px");
		pdfTable.setWidth("100%");
		pdfTable.setSelectable(false);
		pdfTable.setDragMode(TableDragMode.NONE);
		pdfTable.setImmediate(true);

		pdfTable.addListener(new ItemClickEvent.ItemClickListener() {
			public void itemClick(ItemClickEvent event) {
				if (event.getButton() == ItemClickEvent.BUTTON_LEFT) {
					Window subwindowForbidden = new Window();
					subwindowForbidden.setModal(true);
					subwindowForbidden.setWidth("100px");
					Label message = new Label("Operacja zabroniona");
					subwindowForbidden.addComponent(message);

					// Open the subwindow by adding it to the parent window
					getWindow().addWindow(subwindowForbidden);
					getWindow().requestRepaintAll();

				}
			}
		});

	}

	private void createTree() {
		if (tree == null) {
			tree = new Tree();

			HierarchicalContainer c = new HierarchicalContainer();
			c.addContainerProperty(TreePageModel.TREE_PAGE_MODEL,
					Object.class, null);
			c.addContainerProperty(TreePageModel.CAPTION, String.class, null);

			tree.setContainerDataSource(c);
			tree.setItemCaptionPropertyId(TreePageModel.CAPTION);
			tree.setItemCaptionMode(Tree.ITEM_CAPTION_MODE_PROPERTY);

		}
		tree.setImmediate(true);

		// Expand whole tree
		for (Object id : tree.rootItemIds()) {
			tree.expandItemsRecursively(id);
		}

	}

	private void createMenuLayout() {

		if (menuLayout == null) {
			menuLayout = new HorizontalLayout();
		}

		menuLayout.setWidth("800px");
	}

	private void creatCustomLayout() {
		if (cssLayout == null) {
			try {
				cssLayout = new CustomLayout(getNewViolationsFormLayout());
			} catch (Exception e) {
				cssLayout = new CustomLayout("pdfForm");

			}
		}
	}

	protected InputStream getNewViolationsFormLayout() {
		return new ViolationsForm().getLayout();
	}

	public void displayPdf(Page page) {

		pdfTable.removeAllItems();
		pdfTable.setContainerDataSource(page.getIndexedContainer());

	}

	public void addTreeListener(ItemClickListener listener) {
		tree.addListener(listener);
	}

	public void addUpButtonListener(final ClickListener listener) {
		upButton.addListener(listener);
	}

	public void addDownButtonListener(final ClickListener listener) {
		downButton.addListener(listener);
	}

	public void addZoomInButtonListener(final ClickListener listener) {
		zoomIn.addListener(listener);
	}

	public void addZoomOutButtonListener(final ClickListener listener) {
		zoomOut.addListener(listener);
	}

	public void addSearchButtonListener(final ClickListener listener) {
		searchButton.addListener(listener);
	}

	public void addSearchListener(ValueChangeListener listener) {
		searchText.addListener(listener);
	}

	public void addPageListener(ValueChangeListener listener) {
		pages.addListener(listener);

	}

	public void addSearchNextButtonListener(final ClickListener listener) {
		searchNext.addListener(listener);
	}

	public void addSearchPrevButtonListener(final ClickListener listener) {
		searchPrev.addListener(listener);
	}

	public void addTreeActionListener(final Action.Handler listener) {
		tree.addActionHandler(listener);
	}
	
	public void addInfoPanelEditButtonListener(ClickListener listener) {
		infoPanel.addEditButtonListener(listener);
	}
	
	public Tree getTree() {
		return tree;
	}

	public TextField getPages() {
		return pages;
	}

	public Label getAllPages() {
		return allPages;
	}

	public Label getZoomLabel() {
		return zoomLabel;
	}

	public TextField getSearchText() {
		return searchText;
	}

	public void displayMessage(String message) {
		getWindow().showNotification(message);
	}

	public void addSearchContent(List<Integer> search) {

		searchContent.removeAllComponents();
		searchContent.setSpacing(true);
		searchContent.addComponent(new Label("Znaleziono: " + search.size()));

		Button itemButton = null;

		for (Integer item : search) {

			itemButton = new Button();

			itemButton.setIcon(new ThemeResource("page.png"));
			itemButton.setStyleName(BaseTheme.BUTTON_LINK);
			itemButton.addListener(new SearchListener(item));
			itemButton.setCaption("" + item);

			searchContent.addComponent(itemButton);
			searchContent.setComponentAlignment(itemButton,
					Alignment.TOP_CENTER);

		}

		searchContent.requestRepaint();

	}

	public void openPdfViewer() {

		subwindow = new Window();
		subwindow.setWidth("100%");
		subwindow.setModal(true);

		if (subwindow.getParent() != null) {
			// window is already showing
			(subwindow.getParent()).removeWindow(subwindow);
		}

		// Open the subwindow by adding it to the parent window
		getWindow().addWindow(subwindow);
		subwindow.addComponent(pdfWindow);
		getWindow().requestRepaintAll();

	}

	private class SearchListener implements ClickListener {

		private int page;

		SearchListener(int page) {
			this.page = page;
		}

		public void buttonClick(ClickEvent event) {

			displayPdf(dataModel.goPageSearch(page, dataModel
					.getCurrentSearchText()));
			getPages().setValue(page);
			getZoomLabel().setCaption(Zoom.ZOOM_100.toString());

		}
	}

	/**
	 * @return the infoPanel
	 */
	public InfoLayout getInfoPanel() {
		return infoPanel;
	}

	
	
}
